import { computed, defineComponent, h } from "vue";
import { buildProps } from "./types/optionsTypes.ts";
import { FormOption, TFormOptionExtend } from "./types/componentTypes.ts";
import { componentMap } from "./utils/componentMap.ts";
import { getValue } from "./utils/on-change.ts";
import { cloneDeep } from "lodash";

export default defineComponent({
  props: buildProps<FormOption<never>>(),
  setup(_props, { slots }) {
    const pOption = computed(() => cloneDeep(_props.option));
    const pSlots = computed(() => cloneDeep(slots));

    const formState = computed({
      get() {
        return _props.modelValue;
      },
      set(v) {
        Object.assign(_props.modelValue, v);
      },
    });

    const buildOption = (
      option: FormOption<never>,
    ): TFormOptionExtend | undefined => {
      if (option.type !== "custom") {
        const { type, slot = {} } = option;
        const target = componentMap[type];
        if (target) {
          const optionSlots = Object.keys(slot).reduce(
            (slotArr, key) => {
              const currentKey = key as keyof typeof slot;
              const v = slot[currentKey];
              const slotFn = pSlots.value[v as string];
              if (slotFn) {
                slotArr[currentKey] = slotFn;
              }
              return slotArr;
            },
            // @ts-ignore
            {} as Record,
          );
          return {
            ...option,
            slot: optionSlots,
            component: target.component,
          };
        }
        return option;
      }
    };

    return () => {
      const { type, field, component, props, slot } =
        buildOption(pOption.value) || {};
      const currentField = field as keyof typeof formState.value;
      return h(
        component!,
        {
          ...(props ?? {}),
          value: formState.value[currentField],
          onChange: (...args: any[]) => {
            // @ts-ignore
            const v = getValue(type, ...args);
            formState.value = {
              ...formState.value,
              [currentField]: v,
            };
            // @ts-ignore
            props?.onChange?.(...args);
          },
        },
        slot,
      );
    };
  },
});
